'use strict'

const http=require('http');
const fs=require('fs');

const fsp=fs.promises;
/*
.jpg  .jpeg->image/jpeg

.png->image/png

.gif->image/gif

.ico->image/x-icon

.txt->text/plain

.json->text/json 或 application/json

.xml->text/xml 或 application/xml

*/ 


/*-----------------------------解析Body数据-------------------------- */
/**Content-Disposition:form-DataTransfer;name='file';filename="xxx"
*
*
* Content-Type:text/plain 
* @param {string} headerData
*/


function parseBodyHeaders(headerData){
    let hlist=headerData.split('\r\n').filter(p=>p.length>0);

    //解析Content-disposition=》hlist[0]
    //按照; 切分数组，选出从第二个元素开始的数组
    let csplit=hlist[0].split('; ').slice(1);
    let filename
    let name
    for(let a of csplit){
        if(a.indexOf('filename=')===0){
            filename=a.substring(a.indexOf('=')+2,a.length-1)
        }else{
            name=a.substring(a.indexOf('=')+2,a.length-1)
        }
    }

    let headers={}
    let ind=0;
    let k;
    for(let h of hlist){
        ind=h.indexOf(':')
        k=h.substring(0,ind).toLowerCase()
        headers[k]=h.substring(ind+1).trim()
    }

    return {
        filename,
        name,
        headers,
        contentType:headers['content-type']||''
    }
}


function parseBody(bodyData,headers){
    let ctype=headers['content-type'];
    
    let bdy=ctype.substring(ctype.indexOf('=')+1);

    let crlf_bdy=`\r\n--${bdy}`;

    let header_end_index=bodyData.indexOf('\r\n\r\n',crlf_bdy.length);

    let headerData=bodyData.toString('utf8',crlf_bdy.length, header_end_index);

    //解析文件头信息
    let hd=parseBodyHeaders(headerData);

    let file={
        start:header_end_index+4,
        end:bodyData.indexOf(crlf_bdy,header_end_index),
        ...hd
    }
    
    file.length=file.end-file.start;
    return file
}

//解析文件扩展名
function parseExtName(filename){
    if(filename.length<2){
        return ''
    }

    let nsplit=filename.split('.').filter(p=>p.length>0)

    if(nsplit.length<2)return ''

    return `.${nsplit[nsplit.length-1]}`
}
/*-----------------------------解析Body数据--END  ------------------------ */




let html=`
    <!DOCTYPE html>
    <html>
        <head>
            <title>First HTTP</title>
        </head>
        <body>
            你好.
        </body>
    </html>
`

let routerTable={
    GET:{
    '/':async(ctx)=>{
        response.setHeader('content-type', 'text/html; charset=utf-8');
        ctx.end(html);
    },
    '/test':async(ctx)=>{
        let status=parseInt(Math.random()*200)+199
        ctx.response.statusCode=status;
        ctx.end('test end')
    },
    '/upload':async(ctx)=>{
        let stm=fs.createReadStream('./upload.html')
        stm.pipe(ctx.response,{end:false});
        stm.on('end',()=>{
           ctx.end();
        })
    }
    },
    POST:{
    '/data':async(ctx)=>{
        let file=parseBody(ctx.rawBody,ctx.headers)
        console.log(file);

        if(!ctx.rawBody){
            ctx.end();
            return;
           
        }

        let fname=`${Date.now()}-${Math.random()}`+`${parseExtName(file.filename)}`
        let fh=await fsp.open(fname,'a+');
        let fert=await fh.write(ctx.rawBody,file.start,file.length,0)
        // 关闭打开的文件
        fh.close();
        ctx.end(`${fert.bytesWritten}`);
         //ctx.end(ctx.rawBody);

        // let bufferList=[];
        // let bufferLength=0;

        // request.on('data',chunk=>{
        //     bufferLength+=chunk.length
        //     bufferList.push(chunk)
        // })

        // let bodyData=html;
        // request.on('end',()=>{
        //     if(bufferList.length>0){
        //         bodyData=Buffer.concat(bufferList,bufferLength)
        //         bufferList=[];
        //     }

        //     let file=parseBody(bodyData,request.headers)
        //     console.log(file)
        //     //if(bodyData)=if(bodyData!=null||'')
        //     if(bodyData){
        //         response.end(bodyData)
        //     }else{
                
        //         response.end();
        //     }
        // })

        
        }
    }
}
//chunk 以BUffer类型存储的二进制数据
http.createServer(async (request,response)=>{
    let rm=routerTable[request.method];
    let usplit=request.url.split('?');
    let pathname=usplit[0];
    let querystring=usplit[1]||'';
    if(!rm||!rm[pathname]){
        response.statusCode=404;
        response.end('page not found');
        return
    }


    //ctx是context缩写，意为请求上下文，就是一个打包了各种数据和方法的对象
    let ctx={
        method:request.metho,
        path:pathname,
        search:querystring,
        headers:request.headers,
        request:request,
        response:response,
        end:(data,encoding='utf8')=>{
            response.end(data,encoding)
        },
        write(data,encoding='uft8'){
            response.write(data,encoding)
        },
        totalLength:0,
        rawBody:null,
        bufferList:[]
    }

    await new Promise((rv,rj)=>{
        if('PD'.indexOf(request.method[0])>=0){
            request.on('data',chunk=>{
                ctx.bufferList.push(chunk);
                ctx.totalLength+=chunk.length;
            })
        }else{
            request.on('data',data=>{
                response.statusCode=400
                response.end('bad request',()=>{
                    request.destroy();
                })
            })
        }

        let resolved=false;
        request.on('end',()=>{
            resolved=true;
            rv();
        })

        request.on('close',()=>{
            (!resolved)&&rv();
        })

    })

    if(!response.writable||response.writableEnded){
        return
    }
    
    if(ctx.bufferList.length>0){
        ctx.rawBody=Buffer.concat(ctx.bufferList,ctx.totalLength);
        ctx.bufferList=[];
    }

   rm[pathname](ctx);
    
}).listen(3456)